package com.ls.fw.mongo.helper;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.bson.Document;
import org.bson.types.ObjectId;

import com.alibaba.fastjson.JSON;
import com.ls.fw.commons.core.utils.collections.CollectionUtils;
import com.ls.fw.commons.core.utils.collections.MapUtils;
import com.ls.fw.commons.core.utils.string.StringUtils;

public class MongoDbHelper {

	public static final String _ID = "_id";
	
	public static String getId(Document doc){
		return doc.getObjectId(MongoDbHelper._ID).toString();
	}

	public static List<Document> mapToDocument(List<Map<String,Object>> map) throws Exception{
		List<Document> list = null;
		if(CollectionUtils.isNotEmpty(map)){
			list = new ArrayList<Document>();
			for (Map<String, Object> map2 : map) {
				Document doc = mapToDocument(map2);
				if(doc!=null && !doc.isEmpty()){
					list.add(doc);
				}
			}
		}
		return list;
	}
	
	public static Document mapToDocument(Map<String,Object> map) throws Exception{
		final Document doc = new Document();
		if(map!=null && !map.isEmpty()){
			MapUtils.traversal(map, new MapUtils.KeyValueMapper<String,Object>(){

				@Override
				public boolean next(String arg0, Object arg1, int arg2) throws Exception {
					doc.append(arg0, arg1);
					return true;
				}
			});
		}
		return doc;
	}
	
	public  static <T> Document entityToDocument(T t) {
		Document doc = null;
		try {
			Class<? extends Object> cls = t.getClass();
			Field[] fields = cls.getDeclaredFields();
			doc = new Document();
			for (Field field : fields) {
				String name = field.getName();
				String forMethodName = getMethodName(name);
				Method getMethod = null;
				if(field.getGenericType().toString().equals("boolean")) {
					getMethod = cls.getMethod(forMethodName);// 获取get方法
					if(getMethod==null){
						getMethod = cls.getMethod("is"+forMethodName);
					}
				}else{
					getMethod = cls.getMethod("get"+forMethodName);
					if(getMethod==null){
						getMethod = cls.getMethod("get"+name);
					}
				}
				Object value = getMethod.invoke(t, new Object[] {});
				if(value!=null && !isJavaClass(value.getClass())){
					doc.append(name, entityToDocument(value));
				}else{
					if(value!=null){
						doc.append(name, value);
					}
				}
			}
		} catch (Exception e) {
			doc = null;
			throw new IllegalArgumentException(e.getMessage(),e);
		}
		return doc;
	}

	public static <T> T documentToEntity(Document doc, Class<T> cls) {
		T t = null;
		try {
			t = JSON.parseObject(doc.toJson(),cls);
		} catch (Exception e) {
			throw new IllegalArgumentException(e.getMessage(),e);
		}
		Object id  = (Object) doc.get(_ID);
		if(id instanceof ObjectId){
				id = ((ObjectId)id).toString();
		}else{
			if(StringUtils.isBlank(id)){
				id = id.toString();
			}
		}
		try {
			Method setMethod = cls.getDeclaredMethod("set"+_ID,new Class[]{ String.class });// 获取set方法
			setMethod.invoke(t, new Object[] { id });
		} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
		} catch (NoSuchMethodException e) {
		} catch (SecurityException e) {
		} catch (Exception e) {
		}
		return t;
	}
	// 把一个字符串的第一个字母大写、效率是最高的、
	 private static String getMethodName(String fieldName) throws Exception{
		 if(fieldName.startsWith("_")){
			 return fieldName;
		 }
		 byte[] items = fieldName.getBytes();
		  items[0] = (byte) ((char) items[0] - 'a' + 'A');
		  return new String(items);
	 }
	 
	 public static boolean isJavaClass(Class<?> clz) {  
	    return clz != null && clz.getClassLoader() == null;  
	  }  
}
